home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1994
/
MacHack 1994.toast
/
MacHack™ 1987-1994
/
MacHack™ '93
/
Hacks '93
/
HackTV & Example panel comp.
/
HackTV.c
< prev
next >
Wrap
Text File
|
1993-08-18
|
29KB
|
1,168 lines
/*
File: HackTV.c
Contains: Hack TV routines.
Refer to develop Issue 14, "Video Digitizing Under QuickTime",
for details on this code.
This code requires QuickTime 1.5.
This version of HackTV.c includes a section to link in the
example video panel component.
Written by: Gary Woodcock
Copyright: © 1992-1993 by Apple Computer, Inc.
Change History (most recent first):
*/
//-----------------------------------------------------------------------
// Includes
#include <Menus.h>
#include <Windows.h>
#include <QuickDraw.h>
#include <OSEvents.h>
#include <Resources.h>
#include <Desk.h>
#include <Fonts.h>
#include <ToolUtils.h>
#include <QuickTimeComponents.h>
#include <Scrap.h>
#include <Printing.h>
#include <Errors.h>
#include <SysEqu.h>
#include <Folders.h>
#include <Script.h>
#include <Memory.h>
#include <GestaltEqu.h>
#ifndef THINK_C
#include <Packages.h>
#endif THINK_C
#include "softVdig.h"
#include "ExampleVideoPanelPrivate.h"
//-----------------------------------------------------------------------
// Constants
// Menu bar
enum
{
kMenuBarID = 128
};
// Menus
enum
{
kAppleID = 128,
kFileID,
kEditID,
kMonitorID
};
// Apple menu items
enum
{
kAboutItem = 1
};
// File menu items
enum
{
kPageSetupItem = 1,
kPrintItem,
kQuitItem = 4
};
// Edit menu items
enum
{
kUndoItem = 1,
kCutItem = 3,
kCopyItem,
kPasteItem,
kClearItem
};
// Monitor menu items
enum
{
kVideoSettingsItem = 1,
kSoundSettingsItem,
kQuarterSizeItem = 4,
kHalfSizeItem,
kFullSizeItem,
kRecordItem = 8
};
// Dialog IDs
enum
{
kAboutDLOGID = 128,
kMonitorDLOGID
};
// Common DITL items
enum
{
kAboutOKButton = 1,
kAboutOKButtonOutline
};
//-----------------------------------------------------------------------
// Globals
MenuHandle gAppleMenu;
MenuHandle gFileMenu;
MenuHandle gEditMenu;
MenuHandle gMonitorMenu;
EventRecord gTheEvent;
Boolean gQuitFlag;
SeqGrabComponent gSeqGrabber;
SGChannel gVideoChannel;
SGChannel gSoundChannel;
WindowPtr gMonitor;
Rect gActiveVideoRect;
PicHandle gMonitorPICT;
Boolean gFullSize;
Boolean gHalfSize;
Boolean gQuarterSize;
THPrint gPrintRec;
AlignmentProcRecordPtr gSeqGrabberAlignProc;
VideoDigitizerComponent gVdig;
//-----------------------------------------------------------------------
// Prototypes
static void
DoInit (void);
static void
DoMenuSetup (void);
static void
HandleEvent (void);
static void
HandleMouseDown (void);
static void
AdjustMenus (void);
static void
Enable (Handle menu, short item, Boolean ok);
static void
HandleMenu (long menu);
static void
DoAboutDialog (void);
static void
DoQuit (void);
pascal void
AboutDrawProc (DialogPtr theDialog, short theItemNum);
static OSErr
XorRectToRgn (Rect *srcRectA, Rect *srcRectB, RgnHandle *destRgn);
pascal Boolean
SeqGrabberModalFilterProc (DialogPtr theDialog, EventRecord *theEvent,
short *itemHit, long refCon);
static Boolean
HasQuickTime15 (void);
//-----------------------------------------------------------------------
main (void)
{
// Init
DoInit();
DoMenuSetup();
// Eat events until done
do
{
HandleEvent();
}
while (!gQuitFlag);
// Take off, eh?
ExitToShell();
}
//-----------------------------------------------------------------------
static void
DoInit (void)
{
ComponentDescription theDesc;
ComponentResult result = noErr;
Component sgCompID = 0L;
GrafPtr savedPort;
Component vdigCompID; // kck
Component xmplPanelID;
// Set up quit flag
gQuitFlag = false;
// MacMantra™
MaxApplZone();
InitGraf (&qd.thePort);
InitFonts();
FlushEvents (everyEvent, 0);
InitWindows();
InitMenus();
TEInit();
InitDialogs (0L);
InitCursor();
EnterMovies();
MoreMasters();
MoreMasters();
MoreMasters();
MoreMasters();
// Init stuff
gSeqGrabber = 0L;
gVideoChannel = 0L;
gSoundChannel = 0L;
gMonitorPICT = nil;
gPrintRec = (THPrint) NewHandleClear (sizeof (TPrint));
// Find and open a sequence grabber
theDesc.componentType = SeqGrabComponentType;
theDesc.componentSubType = 0L;
theDesc.componentManufacturer = 'appl';
theDesc.componentFlags = 0L;
theDesc.componentFlagsMask = 0L;
sgCompID = FindNextComponent (nil, &theDesc);
if (sgCompID != 0L)
{
gSeqGrabber = OpenComponent (sgCompID);
}
// Find the softVdig
#ifdef DEBUG_IT
vdigCompID = RegisterSoftVdig();
#else
theDesc.componentType = videoDigitizerComponentType;
theDesc.componentSubType = 'soft';
theDesc.componentManufacturer = 'jph ';
theDesc.componentFlags = 0L;
theDesc.componentFlagsMask = 0L;
vdigCompID = FindNextComponent (nil, &theDesc);
SetDefaultComponent (vdigCompID, defaultComponentAnyFlagsAnyManufacturerAnySubType);
#endif DEBUG_IT
theDesc.componentType = videoDigitizerComponentType;
theDesc.componentSubType = 0L;
theDesc.componentManufacturer = 0L;
theDesc.componentFlags = 0L;
theDesc.componentFlagsMask = 0L;
vdigCompID = FindNextComponent (nil, &theDesc);
// Register the example video panel component
#ifdef DEBUG_ME
xmplPanelID = RegisterExampleVideoPanel();
#endif DEBUG_ME
// If we got a sequence grabber, set it up
if (gSeqGrabber != 0L)
{
// Get the monitor
gMonitor = GetNewDialog (kMonitorDLOGID, nil, (WindowPtr) -1L);
if (gMonitor != nil)
{
// Initialize the sequence grabber
GetPort (&savedPort);
SetPort (gMonitor);
ShowWindow (gMonitor);
result = SGInitialize (gSeqGrabber);
if (result == noErr)
{
result = SGSetGWorld (gSeqGrabber, (CGrafPtr) gMonitor, nil);
// Get a video channel
result = SGNewChannel (gSeqGrabber, VideoMediaType, &gVideoChannel);
if ((gVideoChannel != nil) && (result == noErr))
{
short width;
short height;
gQuarterSize = false;
gHalfSize = true;
gFullSize = false;
result = SGGetSrcVideoBounds (gVideoChannel, &gActiveVideoRect);
width = (gActiveVideoRect.right - gActiveVideoRect.left) / 2;
height = (gActiveVideoRect.bottom - gActiveVideoRect.top) / 2;
SizeWindow (gMonitor, width, height, false);
result = SGSetChannelUsage (gVideoChannel, seqGrabPreview | seqGrabRecord | seqGrabPlayDuringRecord);
result = SGSetChannelBounds (gVideoChannel, &(gMonitor->portRect));
}
// Get a sound channel
result = SGNewChannel (gSeqGrabber, SoundMediaType, &gSoundChannel);
if ((gSoundChannel != nil) && (result == noErr))
{
if (HasQuickTime15())
{
// There is a bug in QuickTime 1.5 where a SGChannel of type sound
// will return successfully if there is no sound driver present.
// To get around this, if we're running QT 1.5, we call
// SGGetSoundInputDriver after a successful SGNewChannel call for
// a sound channel to find out if we really got one. QuickTime
// 1.6 has fixed this problem.
short sndDrvrRefNum = SGGetSoundInputDriver (gSoundChannel);
if (sndDrvrRefNum == 0)
{
result = SGDisposeChannel (gSeqGrabber, gSoundChannel);
gSoundChannel = nil;
}
}
if (gSoundChannel != nil)
{
result = SGSetChannelUsage (gSoundChannel, seqGrabPreview | seqGrabRecord);
// Set the volume low to prevent feedback when we start the preview,
// in case the mic is anywhere near the speaker.
result = SGSetChannelVolume (gSoundChannel, 0x0010);
}
}
// Get the alignment proc (for use when dragging the monitor)
result = SGGetAlignmentProc (gSeqGrabber, gSeqGrabberAlignProc);
// Get ready…
SGPrepare (gSeqGrabber, true, true);
}
// Go!
if(result == noErr) result = SGStartPreview (gSeqGrabber);
SetPort (savedPort);
}
}
}
//-----------------------------------------------------------------------
static void
DoMenuSetup (void)
{
Handle theMenuBar = GetNewMBar (kMenuBarID);
// Set up our menus
SetMenuBar (theMenuBar);
gAppleMenu = GetMHandle (kAppleID);
gFileMenu = GetMHandle (kFileID);
gEditMenu = GetMHandle (kEditID);
gMonitorMenu = GetMHandle (kMonitorID);
AddResMenu (gAppleMenu, 'DRVR');
// Last minute adjustments…
AdjustMenus();
}
//-----------------------------------------------------------------------
static void
HandleEvent (void)
{
ComponentResult result = noErr;
// Do system stuff
HiliteMenu (0);
SystemTask();
// Give some time to the sequence grabber
if (gSeqGrabber != 0L)
result = SGIdle (gSeqGrabber);
// Suck an event
if (WaitNextEvent (everyEvent, &gTheEvent, 0, 0))
{
// What was it?
switch (gTheEvent.what)
{
case mouseDown:
{
// Handle it
HandleMouseDown();
break;
}
case keyDown:
case autoKey:
{
char theChar = gTheEvent.message & charCodeMask;
long theMenu = MenuKey (theChar);
// Handle menu command keys
HandleMenu (theMenu);
break;
}
case updateEvt:
{
if ((gMonitor != nil) && ((WindowPtr) (gTheEvent.message) == (WindowPtr) gMonitor))
{
// Eat the update
BeginUpdate (gMonitor);
EndUpdate (gMonitor);
}
break;
}
default: // We don't really care about any other events, but you might, so feel free
{
break;
}
}
}
}
//-----------------------------------------------------------------------
static void
HandleMouseDown (void)
{
WindowPtr theWindow;
short windowCode = FindWindow (gTheEvent.where, &theWindow);
// Where was the mouse down?
switch (windowCode)
{
case inSysWindow:
{
SystemClick (&gTheEvent, theWindow);
break;
}
case inMenuBar:
{
AdjustMenus();
HandleMenu (0L);
break;
}
case inDrag:
{
// Was it the monitor?
if (theWindow == gMonitor)
{
ComponentResult result = noErr;
Rect limitRect;
RgnHandle grayRgn = GetGrayRgn();
Rect boundsRect;
// Find bounds
if (grayRgn != nil)
{
limitRect = (*grayRgn)->rgnBBox;
}
else
{
limitRect = qd.screenBits.bounds;
}
// Pause the sequence grabber
result = SGPause (gSeqGrabber, true);
if (gVideoChannel != nil)
{
// Drag it with the totally cool DragAlignedWindow
// Note that the sequence grabber can get real confused when you use this
// call if you've got multiple video channels - this'll get fixed in the
// next release.
result = SGGetChannelBounds (gVideoChannel, &boundsRect);
DragAlignedWindow (theWindow, gTheEvent.where, &limitRect, &boundsRect, gSeqGrabberAlignProc);
}
else
{
DragWindow (theWindow, gTheEvent.where, &limitRect);
}
// Start up the sequence grabber
result = SGPause (gSeqGrabber, false);
}
break;
}
default:
{
break;
}
}
}
//-----------------------------------------------------------------------
static void
AdjustMenus (void)
{
register WindowPeek wp = nil;
short kind = 0;
Boolean DA = false;
ComponentResult result = noErr;
// What kind of window is frontmost?
wp = (WindowPeek) FrontWindow();
kind = wp ? wp->windowKind : 0;
DA = kind < 0;
// Set our menu item states appropriately
// Apple menu
Enable ((Handle) gAppleMenu, kAboutItem, true);
// File menu
Enable ((Handle) gFileMenu, kPageSetupItem, true);
Enable ((Handle) gFileMenu, kPrintItem, (gVideoChannel != 0L ? true : false));
Enable ((Handle) gFileMenu, kQuitItem, true);
// Edit menu
Enable ((Handle) gEditMenu, kUndoItem, DA);
Enable ((Handle) gEditMenu, kCutItem, DA || (gVideoChannel != 0L));
Enable ((Handle) gEditMenu, kCopyItem, DA || (gVideoChannel != 0L));
Enable ((Handle) gEditMenu, kPasteItem, DA);
Enable ((Handle) gEditMenu, kClearItem, DA);
// Monitor menu
Enable ((Handle) gMonitorMenu, kVideoSettingsItem, (gVideoChannel != 0L ? true : false));
Enable ((Handle) gMonitorMenu, kSoundSettingsItem, (gSoundChannel != 0L ? true : false));
Enable ((Handle) gMonitorMenu, kQuarterSizeItem, (gVideoChannel != 0L ? true : false));
CheckItem (gMonitorMenu, kQuarterSizeItem, gQuarterSize);
Enable ((Handle) gMonitorMenu, kHalfSizeItem, (gVideoChannel != 0L ? true : false));
CheckItem (gMonitorMenu, kHalfSizeItem, gHalfSize);
Enable ((Handle) gMonitorMenu, kFullSizeItem, (gVideoChannel != 0L ? true : false));
CheckItem (gMonitorMenu, kFullSizeItem, gFullSize);
Enable ((Handle) gMonitorMenu, kRecordItem, (gVideoChannel != 0L ? true : false));
// Draw it
DrawMenuBar();
}
//-----------------------------------------------------------------------
static void
Enable (Handle menu, short item, Boolean ok)
{
// Utility routine to enable and disable menu items
if (ok)
{
EnableItem ((MenuHandle) menu, item);
}
else
{
DisableItem ((MenuHandle) menu, item);
}
}
//-----------------------------------------------------------------------
static void
HandleMenu (long theMenu)
{
long mSelect;
short menuID;
short menuItem;
ComponentResult result = noErr;
Str255 menuItemStr;
// Did we get a menu?
if (theMenu == 0L)
{
// Nope, get it from menu select
mSelect = MenuSelect (gTheEvent.where);
}
else
{
// Yep, use it
mSelect = theMenu;
}
// Decode it
menuID = HiWord (mSelect);
menuItem = LoWord (mSelect);
// Which menu is it?
switch (menuID)
{
case kAppleID:
{
if (menuItem == kAboutItem)
{
// Do the boring about box
DoAboutDialog();
}
else // It's a DA
{
Str255 name;
GrafPtr savedPort;
// Open the DA
GetPort (&savedPort);
GetItem (gAppleMenu, menuItem, name);
OpenDeskAcc (name);
SetPort (savedPort);
}
break;
}
case kFileID:
{
switch (menuItem)
{
case kPageSetupItem:
{
// Do the page setup dialog
PrOpen();
PrStlDialog (gPrintRec);
PrClose();
break;
}
case kPrintItem:
{
TPPrPort printPort;
TPrStatus printStatus;
// Copy a frame from the monitor
if (gMonitorPICT != nil)
{
KillPicture (gMonitorPICT);
}
gMonitorPICT = nil;
result = SGGrabPict (gSeqGrabber, &gMonitorPICT, nil, 0, grabPictOffScreen);
if ((result == noErr) && (gMonitorPICT != nil))
{
// Print it
HLock ((Handle) gMonitorPICT);
PrOpen();
if (PrJobDialog (gPrintRec))
{
printPort = PrOpenDoc (gPrintRec, nil, nil);
result = PrError();
PrOpenPage (printPort, 0);
result = PrError();
DrawPicture (gMonitorPICT, &((**gMonitorPICT).picFrame));
PrClosePage (printPort);
result = PrError();
PrCloseDoc (printPort);
result = PrError();
if ((**gPrintRec).prJob.bJDocLoop == bSpoolLoop)
{
PrPicFile (gPrintRec, 0, 0, 0, &printStatus);
result = PrError();
}
}
PrClose();
result = PrError();
HUnlock ((Handle) gMonitorPICT);
}
break;
}
case kQuitItem:
{
// Let's scram
DoQuit();
break;
}
}
break;
}
case kEditID:
{
// Is this a DA kind of thing?
if (!SystemEdit (menuItem - 1))
{
// We only do cut and copy
if ((menuItem == kCutItem) || (menuItem == kCopyItem))
{
// Copy a frame from the monitor
if (gMonitorPICT != nil)
{
KillPicture (gMonitorPICT);
}
gMonitorPICT = nil;
result = SGGrabPict (gSeqGrabber, &gMonitorPICT, nil, 0, grabPictOffScreen);
if ((result == noErr) && (gMonitorPICT != nil))
{
result = ZeroScrap();
HLock ((Handle) gMonitorPICT);
result = PutScrap (GetHandleSize ((Handle) gMonitorPICT), 'PICT', *(Handle)gMonitorPICT);
HUnlock ((Handle) gMonitorPICT);
if (result != noErr)
{
// Cut or copy failed, probably due to lack of memory
}
}
}
}
break;
}
case kMonitorID:
{
switch (menuItem)
{
short width;
short height;
Rect curBounds;
Rect curVideoRect;
Rect newVideoRect;
Rect newBounds;
Rect maxBoundsRect;
GrafPtr savedPort;
RgnHandle deadRgn;
Rect boundsRect;
case kVideoSettingsItem:
{
if ((gSeqGrabber != 0L) && (gVideoChannel != 0L))
{
Rect newActiveVideoRect;
Rect adjustedActiveVideoRect;
// Get our current state
result = SGGetChannelBounds (gVideoChannel, &curBounds);
result = SGGetVideoRect (gVideoChannel, &curVideoRect);
// Pause
result = SGPause (gSeqGrabber, true);
// Do the dialog thang
result = SGSettingsDialog (gSeqGrabber, gVideoChannel, 0,
nil, 0L, SeqGrabberModalFilterProc, (long) StripAddress ((Ptr) gMonitor));
// What happened?
result = SGGetVideoRect (gVideoChannel, &newVideoRect);
result = SGGetSrcVideoBounds (gVideoChannel, &newActiveVideoRect);
// Set up our port
GetPort (&savedPort);
SetPort (gMonitor);
// Has our active rect changed?
// If so, it's because our video standard changed (e.g., NTSC to PAL),
// and we need to adjust our monitor window
if (!EqualRect (&gActiveVideoRect, &newActiveVideoRect))
{
if (gFullSize)
{
width = newActiveVideoRect.right - newActiveVideoRect.left;
height = newActiveVideoRect.bottom - newActiveVideoRect.top;
gActiveVideoRect = newActiveVideoRect;
SizeWindow (gMonitor, width, height, false);
result = SGSetChannelBounds (gVideoChannel, &(gMonitor->portRect));
}
else if (gHalfSize)
{
width = (newActiveVideoRect.right - newActiveVideoRect.left) / 2;
height = (newActiveVideoRect.bottom - newActiveVideoRect.top) / 2;
gActiveVideoRect = newActiveVideoRect;
SizeWindow (gMonitor, width, height, false);
result = SGSetChannelBounds (gVideoChannel, &(gMonitor->portRect));
}
else if (gQuarterSize)
{
width = (newActiveVideoRect.right - newActiveVideoRect.left) / 4;
height = (newActiveVideoRect.bottom - newActiveVideoRect.top) / 4;
gActiveVideoRect = newActiveVideoRect;
SizeWindow (gMonitor, width, height, false);
result = SGSetChannelBounds (gVideoChannel, &(gMonitor->portRect));
}
}
// Has our crop changed?
// This code shows how to be crop video panel friendly
// Two important things -
// 1) Be aware that you might have been cropped and adjust your
// video window appropriately
// 2) Be aware that you might have been adjusted and attempt to
// account for this. Adjusting refers to using the digitizer
// rect to "adjust" the active source rect within the maximum
// source rect. This is useful if you're getting those nasty
// black bands on the sides of your video display - you can use
// the control-arrow key sequence to shift the active source
// rect around when you're in the crop video panel
adjustedActiveVideoRect = gActiveVideoRect;
if (!EqualRect (&curVideoRect, &newVideoRect))
{
if ((newVideoRect.left < gActiveVideoRect.left) ||
(newVideoRect.right > gActiveVideoRect.right) ||
(newVideoRect.top < gActiveVideoRect.top) ||
(newVideoRect.bottom > gActiveVideoRect.bottom))
{
if (newVideoRect.left < gActiveVideoRect.left)
{
adjustedActiveVideoRect.left = newVideoRect.left;
adjustedActiveVideoRect.right -= (gActiveVideoRect.left - newVideoRect.left);
}
if (newVideoRect.right > gActiveVideoRect.right)
{
adjustedActiveVideoRect.right = newVideoRect.right;
adjustedActiveVideoRect.left += (newVideoRect.right - gActiveVideoRect.right);
}
if (newVideoRect.top < gActiveVideoRect.top)
{
adjustedActiveVideoRect.top = newVideoRect.top;
adjustedActiveVideoRect.bottom -= (gActiveVideoRect.top - newVideoRect.top);
}
if (newVideoRect.bottom > gActiveVideoRect.bottom)
{
adjustedActiveVideoRect.bottom = newVideoRect.bottom;
adjustedActiveVideoRect.top += (newVideoRect.bottom - gActiveVideoRect.bottom);
}
newBounds = newVideoRect;
MapRect (&newBounds, &adjustedActiveVideoRect, &(gMonitor->portRect));
}
else // Can't tell if we've been adjusted (digitizer rect is smaller on all sides
// than the active source rect)
{
newBounds = newVideoRect;
MapRect (&newBounds, &gActiveVideoRect, &(gMonitor->portRect));
}
width = newBounds.right - newBounds.left;
height = newBounds.bottom - newBounds.top;
result = SGSetChannelBounds (gVideoChannel, &newBounds);
}
// Clean out the part of the port that isn't being drawn in
deadRgn = NewRgn();
if (deadRgn != nil)
{
result = SGGetChannelBounds (gVideoChannel, &boundsRect);
result = XorRectToRgn (&boundsRect, &(gMonitor->portRect), &deadRgn);
EraseRgn (deadRgn);
DisposeRgn (deadRgn);
}
SetPort (savedPort);
// The pause that refreshes
result = SGPause (gSeqGrabber, false);
}
break;
}
case kSoundSettingsItem:
{
if ((gSeqGrabber != 0L) && (gSoundChannel != 0L))
{
// Do the dialog thang
result = SGSettingsDialog (gSeqGrabber, gSoundChannel, 0,
nil, 0L, SeqGrabberModalFilterProc, (long) StripAddress ((Ptr) gMonitor));
}
break;
}
case kQuarterSizeItem:
{
// New width and height
width = (gActiveVideoRect.right - gActiveVideoRect.left) / 4;
height = (gActiveVideoRect.bottom - gActiveVideoRect.top) / 4;
// Set flags and menus
gQuarterSize = true;
gHalfSize = false;
gFullSize = false;
AdjustMenus();
// Resize the monitor
GetPort (&savedPort);
SetPort (gMonitor);
result = SGPause (gSeqGrabber, true);
result = SGGetChannelBounds (gVideoChannel, &curBounds);
maxBoundsRect = gMonitor->portRect;
SizeWindow (gMonitor, width, height, false);
MapRect (&curBounds, &maxBoundsRect, &(gMonitor->portRect));
result = SGSetChannelBounds (gVideoChannel, &curBounds);
// Clean out part of port we're not drawing in
deadRgn = NewRgn();
if (deadRgn != nil)
{
result = SGGetChannelBounds (gVideoChannel, &boundsRect);
result = XorRectToRgn (&boundsRect, &(gMonitor->portRect), &deadRgn);
EraseRgn (deadRgn);
DisposeRgn (deadRgn);
}
SetPort (savedPort);
result = SGPause (gSeqGrabber, false);
break;
}
case kHalfSizeItem:
{
// New width and height
width = (gActiveVideoRect.right - gActiveVideoRect.left) / 2;
height = (gActiveVideoRect.bottom - gActiveVideoRect.top) / 2;
// Set flags and menus
gQuarterSize = false;
gHalfSize = true;
gFullSize = false;
AdjustMenus();
// Resize the monitor
GetPort (&savedPort);
SetPort (gMonitor);
result = SGPause (gSeqGrabber, true);
result = SGGetChannelBounds (gVideoChannel, &curBounds);
maxBoundsRect = gMonitor->portRect;
SizeWindow (gMonitor, width, height, false);
MapRect (&curBounds, &maxBoundsRect, &(gMonitor->portRect));
result = SGSetChannelBounds (gVideoChannel, &curBounds);
// Clean out part of port we're not drawing in
deadRgn = NewRgn();
if (deadRgn != nil)
{
result = SGGetChannelBounds (gVideoChannel, &boundsRect);
result = XorRectToRgn (&boundsRect, &(gMonitor->portRect), &deadRgn);
EraseRgn (deadRgn);
DisposeRgn (deadRgn);
}
SetPort (savedPort);
result = SGPause (gSeqGrabber, false);
break;
}
case kFullSizeItem:
{
// New width and height
width = gActiveVideoRect.right - gActiveVideoRect.left;
height = gActiveVideoRect.bottom - gActiveVideoRect.top;
// Set flags and menus
gQuarterSize = false;
gHalfSize = false;
gFullSize = true;
AdjustMenus();
// Resize the monitor
GetPort (&savedPort);
SetPort (gMonitor);
result = SGPause (gSeqGrabber, true);
result = SGGetChannelBounds (gVideoChannel, &curBounds);
maxBoundsRect = gMonitor->portRect;
SizeWindow (gMonitor, width, height, false);
MapRect (&curBounds, &maxBoundsRect, &(gMonitor->portRect));
result = SGSetChannelBounds (gVideoChannel, &curBounds);
// Clean out part of port we're not drawing in
deadRgn = NewRgn();
if (deadRgn != nil)
{
result = SGGetChannelBounds (gVideoChannel, &boundsRect);
result = XorRectToRgn (&boundsRect, &(gMonitor->portRect), &deadRgn);
EraseRgn (deadRgn);
DisposeRgn (deadRgn);
}
SetPort (savedPort);
result = SGPause (gSeqGrabber, false);
break;
}
case kRecordItem:
{
FSSpec theFSSpec;
long savedDirID = *(long *) CurDirStore;
long dirID;
short savedVRefNum = *(short *) SFSaveDisk;
short vRefNum;
result = FindFolder (kOnSystemDisk, kDesktopFolderType, kCreateFolder,
&vRefNum, &dirID);
*(short *)SFSaveDisk = -vRefNum;
*(long *)CurDirStore = dirID;
result = FSMakeFSSpec (vRefNum, dirID, "\pHack MooV", &theFSSpec);
result = DeleteMovieFile (&theFSSpec);
result = CreateMovieFile (&theFSSpec, 'TVOD', smSystemScript,
createMovieFileDontOpenFile | createMovieFileDontCreateMovie,
nil, nil);
result = SGStop (gSeqGrabber);
result = SGSetDataOutput (gSeqGrabber, &theFSSpec, seqGrabToDisk);
result = SGStartRecord (gSeqGrabber);
while (!Button() && (result == noErr))
{
result = SGIdle (gSeqGrabber);
}
result = SGStop (gSeqGrabber);
result = SGStartPreview (gSeqGrabber);
*(short *)SFSaveDisk = savedVRefNum;
*(long *)CurDirStore = savedDirID;
break;
}
default:
{
break;
}
}
}
default:
{
break;
}
}
}
//-----------------------------------------------------------------------
static void
DoAboutDialog (void)
{
short itemHit;
short itemType;
Handle itemHandle;
Rect itemRect;
DialogPtr aboutDialog = GetNewDialog (kAboutDLOGID, nil, (WindowPtr)-1L);
// Do the boring about dialog
GetDItem (aboutDialog, kAboutOKButtonOutline, &itemType, &itemHandle, &itemRect);
SetDItem (aboutDialog, kAboutOKButtonOutline, itemType,
(Handle) AboutDrawProc, &itemRect);
ShowWindow (aboutDialog);
do
{
ModalDialog (nil, &itemHit);
}
while (itemHit != kAboutOKButton);
DisposDialog (aboutDialog);
}
//-----------------------------------------------------------------------
pascal void
AboutDrawProc (DialogPtr theDialog, short theItemNum)
{
PenState thePenState;
OSErr result = noErr;
Rect itemRect;
Handle itemHandle;
short itemType;
// Set up the pen
GetPenState (&thePenState);
GetDItem (theDialog, theItemNum, &itemType, &itemHandle, &itemRect);
// What item do we need to draw?
switch (theItemNum)
{
case kAboutOKButtonOutline:
PenNormal();
PenMode (patCopy);
PenSize (3, 3);
InsetRect (&itemRect, -4, -4);
FrameRoundRect (&itemRect, 16, 16);
break;
default:
break;
}
// Restore the pen
SetPenState (&thePenState);
}
//-----------------------------------------------------------------------
static OSErr
XorRectToRgn (Rect *srcRectA, Rect *srcRectB, RgnHandle *destRgn)
{
RgnHandle srcRgnA = NewRgn();
RgnHandle srcRgnB = NewRgn();
OSErr result = noErr;
if ((destRgn != nil) && (*destRgn != nil))
{
if ((srcRgnA != nil) &&
(srcRgnB != nil))
{
RectRgn (srcRgnA, srcRectA);
RectRgn (srcRgnB, srcRectB);
XorRgn (srcRgnA, srcRgnB, *destRgn);
DisposeRgn (srcRgnA);
DisposeRgn (srcRgnB);
}
else
{
result = memFullErr;
}
}
else
{
result = nilHandleErr;
}
return (result);
}
//-----------------------------------------------------------------------
pascal Boolean
SeqGrabberModalFilterProc (DialogPtr theDialog, EventRecord *theEvent,
short *itemHit, long refCon)
{
// Ordinarily, if we had multiple windows we cared about, we'd handle
// updating them in here, but since we don't, we'll just clear out
// any update events meant for us
Boolean handled = false;
if ((theEvent->what == updateEvt) &&
((WindowPtr) theEvent->message == (WindowPtr) refCon))
{
BeginUpdate ((WindowPtr) refCon);
EndUpdate ((WindowPtr) refCon);
handled = true;
}
return (handled);
}
//-----------------------------------------------------------------------
static Boolean
HasQuickTime15 (void)
{
long result;
OSErr err = Gestalt (gestaltQuickTime, &result);
return (((err == noErr) & (result >= 0x0150)) ? true: false);
}
//-----------------------------------------------------------------------
static void
DoQuit (void)
{
ComponentResult result = noErr;
// Clean up
if (gSeqGrabber != 0L)
{
result = CloseComponent (gSeqGrabber);
gSeqGrabber = 0L;
}
if (gMonitor != nil)
{
DisposeWindow (gMonitor);
}
// Set quit flag
gQuitFlag = true;
ExitMovies();
}
//-----------------------------------------------------------------------